<template>
  <div class="home">
    <div class="fanyaData">
      <!-- 顶部按钮 -->
      <div class="btn_group">
        <!-- 上传 -->
        <button class="btn_update" @click="updateFile">上传</button>
        <!-- 搜索框 -->
        <div class="dataSearch">
          <!-- 输入框 -->
          <input type="text" class="ipt_val" placeholder="搜索" v-model="formData.search"/>
          <!-- 放大镜 -->
          <input type="button" class="ipt_fdj" @click="getFiles"/>
          <!-- 搜索按钮 -->
          <button type="button" class="ipt_search" @click="getFiles">搜索</button>
        </div>
      </div>
      <div class="info">
        <!-- 面包屑 -->
        <div class="breadcrumb">
          <span v-for="(item, i) in breadcrumb" :key="item.key" @click="goBack(i)">{{ item.fileName }}</span>
        </div>
        <div>
          <!-- 已选个数 -->
          <span v-show="checkedList.length">
						已选&nbsp;<span style="color: #3A8BFF;">{{ this.checkedList.length }}</span>&nbsp;个，
					</span>
          <!-- 总数 -->
          <span>共&nbsp;{{ this.countTotalFile }}&nbsp;个</span>
        </div>
      </div>
      <!-- 表格区 -->
      <div class="tableData">
        <!-- 表头 -->
        <div class="table_header table_row">
          <div :style="{flex: 1}">
            <input type="checkbox" :checked="allBoxValue" @click="checkAll"/>
          </div>
          <div :style="{flex: 11}">文件名</div>
          <div :style="{flex: 4}"></div>
          <div :style="{flex: 2}">大小</div>
          <div :style="{flex: 3}" @click="sortList">
            创建日期
            <span :class="formData.reverse ? 'sort_down' : 'sort_up'"></span>
          </div>
        </div>
        <!-- 列表 -->
        <div class="table_list">
          <!-- 文件夹 -->
          <div v-for="(item, i) in files.folder" :key="item.id" class="list_item table_row"
               :class="{active: checkedList.indexOf(item.id) !== -1}">
            <div :style="{flex: 1}">
              <input type="checkbox" disabled/>
            </div>
            <div :style="{flex: 11}" @click="clickFolder(i)">
              <img :src="item.icon" alt=""/>
              <a href="javascript:;">{{ item.fileName }}</a>
            </div>
            <div :style="{flex: 4}"></div>
            <div :style="{flex: 2}">{{ item.fileSize }}</div>
            <div :style="{flex: 3}">{{ item.createTime }}</div>
          </div>
          <!-- 文件 -->
          <div v-for="(item, i) in files.file" :key="item.id" class="list_item table_row"
               :class="{active: checkedList.indexOf(item.id) !== -1}" @contextmenu.prevent="openRightMenu($event,item)">
            <div :style="{flex: 1}">
              <input type="checkbox" name="file" v-model="checkedList" :value="item.id"/>
            </div>
            <div :style="{flex: 11}">
              <img :src="item.icon" alt=""/>
              <a href="javascript:;">{{ item.fileName }}</a>
            </div>
            <div :style="{flex: 4}"></div>
            <div :style="{flex: 2}">{{ item.fileSize }}</div>
            <div :style="{flex: 3}">{{ item.createTime }}</div>
          </div>
        </div>
      </div>
    </div>
    <el-dialog :visible.sync="dialogVisible" width="66%">
      <uploader
        ref="uploader"
        :options="options"
        :file-status-text="fileStatusText"
        :autoStart="false"
        @file-added="onFileAdded"
        @file-progress="onFileProgress"
        @file-success="onFileSuccess"
        @file-error="onFileError"
        class="uploader">
        <uploader-unsupport></uploader-unsupport>
        <uploader-drop>
          <uploader-btn class="upfile"><i class="iconfont icon-upload"></i> 上传文件</uploader-btn>
          <uploader-btn class="updir" :directory="true"><i class="iconfont icon-dir"></i> 上传文件夹</uploader-btn>
        </uploader-drop>
        <uploader-list></uploader-list>
      </uploader>

      <span slot="footer" class="dialog-footer">
            <el-button @click="dialogVisible = false">后台上传</el-button>
        </span>
    </el-dialog>

    <!--右键菜单-->
    <ul v-show="rightClickVisible" :style="{left:rightClick.left+'px',top:rightClick.top+'px'}" class="contextmenu">
      <!--<li v-if="rightClickItem.fileType==99" @click="handleClickFolder(rightClickItem)">打开</li>-->
      <li @click="handleDownloadFile(rightClick.rightClickItem)">下载</li>
      <li @click="handleDelete(rightClick.rightClickItem)">删除</li>
      <!--<li @click="handlePreviewFile(rightClickItem)" v-if="rightClickItem.fileType!=99">预览</li>
      <li @click="handleUpdate(rightClickItem)">编辑</li>-->
    </ul>
  </div>
</template>

<script>
    import SparkMD5 from 'spark-md5';

    export default {
        name: 'Home1',
        data() {
            return {
                dialogVisible: false,
                // 面包屑
                breadcrumb: [{
                    id: 0,
                    name: '全部文件'
                }],
                // 表单数据
                formData: {
                    // 当前文件夹id，默认全部文件最上层为0
                    currentFolderId: 0,
                    // 搜索框内容
                    search: '',
                    // 是否逆序
                    reverse: false
                },
                // 文件列表
                files: {
                    folder: [],
                    file: []
                },
                // 被选中的文件id列表
                checkedList: [],

                //右键菜单
                rightClick: {
                    rightClickItem: null,
                    top: 0,
                    left: 0
                },
                rightClickVisible: false,

                //文件上传参数
                options: {
                    target: 'http://101.43.71.61:8080/disk/upload/uploadChunk',
                    chunkSize: 1024 * 512,  //2MB
                    simultaneousUploads: 1, //并发上传数
                    headers: {
                        'token': window.localStorage.getItem("token")
                    },
                    maxChunkRetries: 2, //最大自动失败重试上传次数
                    parseTimeRemaining: function (timeRemaining, parsedTimeRemaining) { //格式化时间
                        return parsedTimeRemaining
                            .replace(/\syears?/, '年')
                            .replace(/\days?/, '天')
                            .replace(/\shours?/, '小时')
                            .replace(/\sminutes?/, '分钟')
                            .replace(/\sseconds?/, '秒')
                    },
                    testChunks: true,   //开启服务端分片校验
                    // 服务器分片校验函数
                    checkChunkUploadedByResponse: (chunk, message) => {
                        let obj = JSON.parse(message).data;
                        if (obj.isExist) {
                            this.statusTextMap.success = '秒传文件';
                            return true;
                        }

                        return (obj.uploaded || []).indexOf(chunk.offset + 1) >= 0
                    },
                },

                statusTextMap: {
                    success: '上传成功',
                    error: '上传出错了',
                    uploading: '上传中...',
                    paused: '暂停',
                    waiting: '等待中...',
                    cmd5: '计算md5...'
                },

                fileStatusText: (status, response) => {
                    return this.statusTextMap[status];
                },
				courseStudentId:localStorage.getItem("ClassId"),
            }
        },
        computed: {
            // 文件总数
            countTotalFile() {
                return this.files.file.length + this.files.folder.length
            },
            // 全选按钮状态
            allBoxValue() {
                return this.checkedList.length === this.files.file.length
            }
        },
        created() {
            // 清空被选中文件id列表
            this.checkedList = [];
            this.getFiles()
        },
        methods: {
            // 获取课程文件列表
            getFiles() {
                // params参数：课程Id
				// alert( this.courseStudentId);
                let courseId =this.courseStudentId;
                let token = window.localStorage.getItem("token");
                this.axios.get('/disk/search/findForCourse', {
                    headers: {
                        token: token
                    },
                    params: {
                        courseId
                    }
                }).then(response => {
                    let data = response.data.data;
                    this.files.folder = data.folder;
                    this.files.file = data.file;
                    this.breadcrumb = [
                        {
                            id: data.id,
                            fileName: "全部文件"
                        }
                    ];
                    //当前文件夹Id
                    this.formData.currentFolderId = data.id;
                }).catch(error => {
                    console.log(error);
                });
            },

            //获取文件夹文件列表
            getFolderFiles(pid) {
                let token = window.localStorage.getItem("token");
                this.axios.get('/disk/search/findForFolder', {
                    headers: {
                        token: token
                    },
                    params: {
                        pid
                    }
                }).then(response => {
                    let data = response.data.data;
                    this.files.folder = data.folder;
                    this.files.file = data.file;
                }).catch(error => {
                    console.log(error);
                });
            },

            // 上传文件
            updateFile() {
                this.dialogVisible = true;
            },

            // 点击某文件夹
            clickFolder(index) {
                // 更新面包屑导航
                this.breadcrumb.push({
                    id: this.files.folder[index].id,
                    fileName: this.files.folder[index].fileName
                });
                let folderId = this.files.folder[index].id;
                // 更新文件列表
                this.getFolderFiles(folderId);
                // 更新当前文件夹Id
                this.formData.currentFolderId = folderId;
            },

            // 回到某文件夹下
            goBack(index) {
                if (index === this.breadcrumb.length - 1) return;
                let folderId = this.breadcrumb[index].id;
                this.getFolderFiles(folderId);
                this.formData.currentFolderId = folderId;
                this.breadcrumb = this.breadcrumb.slice(0, index + 1);
            },

            // 选中或取消全选
            checkAll(e) {
                this.checkedList = e.target.checked ?
                    this.files.file.map(item => item.id) : []
            },

            // 点击排序
            sortList() {
                this.files.folder.sort(this.compareCreateTime);
                this.files.file.sort(this.compareCreateTime);
                //排序方式取反
                this.formData.reverse = !this.formData.reverse;
            },
            //文件按照创建时间排序
            compareCreateTime(file1, file2) {
                if (this.formData.reverse) {
                    if (file1.createTime < file2.createTime) {
                        return 1;
                    }
                    return -1;
                } else {
                    if (file1.createTime < file2.createTime) {
                        return -1;
                    }
                    return 1;
                }
            },

            onFileAdded(file) {
                // 计算MD5
                this.computeMD5(file);
                file.folderId = this.formData.currentFolderId;
            },
            //计算MD5
            computeMD5(file) {
                let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
                    chunkSize = 2097152,
                    chunks = Math.ceil(file.size / chunkSize),
                    currentChunk = 0,
                    spark = new SparkMD5.ArrayBuffer(),
                    fileReader = new FileReader();

                let time = new Date().getTime();
                file.cmd5 = true;

                fileReader.onload = (e) => {
                    spark.append(e.target.result);   // Append array buffer
                    currentChunk++;
                    if (currentChunk < chunks) {
                        //console.log(`第${currentChunk}分片解析完成, 开始第${currentChunk +1} / ${chunks}分片解析`);
                        let percent = Math.floor(currentChunk / chunks * 100);
                        file.cmd5progress = percent;
                        loadNext();
                    } else {
                        console.log('finished loading');
                        let md5 = spark.end();
                        console.log(`MD5计算完成：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`);
                        spark.destroy(); //释放缓存
                        file.uniqueIdentifier = md5; //将文件md5赋值给文件唯一标识
                        file.cmd5 = false; //取消计算md5状态
                        file.resume(); //开始上传
                    }
                };
                fileReader.onerror = () => {
                    console.warn('oops, something went wrong.');
                    file.cancel();
                };
                let loadNext = () => {
                    let start = currentChunk * chunkSize,
                        end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

                    fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
                };
                loadNext();
            },
            //文件进度的回调
            onFileProgress(rootFile, file, chunk) {
                console.log(`上传中 ${file.name}，chunk：${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`)
            },
            //文件上传成功
            onFileSuccess(rootFile, file, response, chunk) {
                let resp = JSON.parse(response);
                let pid = file.folderId;
                //合并分片
                if (resp.code === 200) {
                    let token = window.localStorage.getItem("token");
                    this.axios.post('/disk/upload/mergeChunk', {
                        pid: pid,
                        filename: file.name,
                        identifier: file.uniqueIdentifier,
                        totalSize: file.size,
                        totalChunks: chunk.offset + 1,
                        relativePath: file.relativePath
                    }, {
                        headers: {
                            'token': token
                        }
                    }).then(res => {
                        if (res.data.code === 200) {
                            let pid = this.formData.currentFolderId;
                            //刷新数据
                            if (pid === file.folderId) {
                                this.getFolderFiles(pid)
                            }
                        } else {
                            alert(file.name + "上传出错")
                        }
                    }).catch(error => {
                        console.log(error);
                    });
                }
            },
            //文件上传失败
            onFileError(rootFile, file, response, chunk) {
                console.log('Error:', response)
            },

            //右键菜单
            openRightMenu(e, item) {
                this.rightClick.rightClickItem = item;
                let x = e.clientX;
                let y = e.clientY;
                this.rightClick.top = y;
                this.rightClick.left = x;
                this.rightClickVisible = true;
            },
            closeMenu() {
                this.rightClickVisible = false;
            },
            //下载文件
            handleDownloadFile(rightClickItem) {
                let file = rightClickItem;
                let fileId = file.id;
                let token = window.localStorage.getItem("token");
                this.axios.post("/disk/download/file", {
                    fileId: fileId
                }, {
                    headers: {
                        token: token
                    },
                    responseType: 'arraybuffer'
                }).then(res => {
                    console.log(res);
                    let content = res.data;
                    // 组装a标签
                    let elink = document.createElement("a");
                    // 设置下载文件名
                    elink.download = file.fileName;
                    elink.style.display = "none";
                    let blob = new Blob([content]);
                    elink.href = URL.createObjectURL(blob);
                    document.body.appendChild(elink);
                    elink.click();
                    document.body.removeChild(elink);
                    console.log("文件下载成功");
                }).catch(err => {
                    console.log(err);
                })
            },
            //删除文件
            handleDelete(rightClickItem) {
                //需删除的文件id
                let fileId = rightClickItem.id;
                let token = window.localStorage.getItem("token");
                this.axios.get("/disk/common/delete", {
                    headers: {
                        token: token
                    },
                    params: {
                        fileId
                    }
                }).then(res => {
                    let folderId = this.formData.currentFolderId;
                    this.getFolderFiles(folderId);
                    alert("文件已删除");
                }).catch(err => {
                    alert("文件删除失败");
                    console.log(err);
                })
            }
        },
        watch: {
            rightClickVisible(value) {
                if (value) {
                    document.body.addEventListener('click', this.closeMenu)
                } else {
                    document.body.removeEventListener('click', this.closeMenu)
                }
            }
        }
    }
</script>

<style lang="scss" scoped="scoped">
  .home {
    height: 830px;
    width: 100%;


    .fanyaData {
      padding: 30px;
      min-height: 600px;
      background-color: #ffff;

      // 顶部按钮组
      .btn_group {
        display: flex;
        justify-content: space-between;

        // 上传
        .btn_update {
          padding: 0 22px;
          border: none;
          height: 36px;
          border-radius: 5px;
          background-color: #03d3bd;
          color: #fff;

          &:hover {
            cursor: pointer;
          }
        }

        // 搜索框
        .dataSearch {
          position: relative;
          width: 300px;
          height: 36px;

          // 输入框
          .ipt_val {
            position: absolute;
            left: 0;
            top: 0;
            padding: 0 14px 0 28px;
            outline: none;
            border-color: #d5d7d9;
            width: 170px;
            height: 34px;
            font-size: 14px;
            color: #181e33;
            border: 1px solid #e5e5e5;
            background: #f5f6f7;
            border-radius: 40px;

            &:hover {

              border: 1px solid #03d3bd;
            }

            &:focus {
              border: 1px solid #03d3bd;
            }
          }

          // 放大镜
          .ipt_fdj {
            position: absolute;
            // right: 14px;
            left: 8px;
            top: 8px;
            border: none;
            width: 18px;
            height: 18px;
            background-color: pink;
            background: url(/images/search_ico_new.png);
            background-size: 18px;

            &:hover {
              cursor: pointer;
              background-position: 0 -22px;
            }
          }

          // 搜索按钮
          .ipt_search {
            // width: 40px;
            position: absolute;
            right: 0;
            top: 0;
            padding: 0 22px;
            border: none;
            height: 36px;
            border-radius: 17px;
            background-color: #03d3bd;
            color: #fff;

            &:hover {
              cursor: pointer;
              color: #ffffff;
            }
          }
        }
      }

      .info {
        display: flex;
        justify-content: space-between;
        width: 100%;
        padding: 20px 0 10px 0;
        font-size: 12px;
        color: #8a8b99;

        // 面包屑
        .breadcrumb {
          span:not(:last-child) {
            &:hover {
              cursor: pointer;
              color: #3A8BFF;
            }

            &::after {
              content: '';
              display: inline-block;
              width: 6px;
              height: 10px;
              margin: 0 4px;
              background: url(/images/breadcrumb.png);
            }
          }
        }
      }

      // 表格区
      .tableData {

        // 表头
        .table_header {
          display: flex;
          justify-content: space-between;
          align-items: center;
          height: 40px;
          background-color: #f5f6f7;
          font-size: 14px;
          color: #8a8b99;

          .sort_up,
          .sort_down {
            width: 13px;
            height: 13px;
            margin: 3px 0 3px 6px;
            display: inline-block;
            overflow: hidden;
            vertical-align: middle;
            cursor: pointer;
            background: url(/images/sort_icon.png) no-repeat 0 0;
            background-size: 10px auto;
          }

          .sort_up:hover {
            background-position: 0 -15px;
          }

          .sort_down {
            background-position: 0 -30px;
          }

          .sort_down:hover {
            background-position: 0 -45px;
          }
        }

        // 行布局
        .table_row {
          padding-left: 15px;

          div {
            display: flex;
            justify-content: flex-start;
            align-items: center;
            line-height: 40px;
            height: 100%;

            input {
              width: 18px;
              height: 18px;
              cursor: pointer;
            }
          }
        }

        // 列表
        .table_list {
          margin-top: 10px;

          // 列表项
          .list_item {
            display: flex;
            height: 66px;
            font-size: 14px;

            &.active {
              background-color: #f0f6ff;
            }

            &:hover {
              cursor: pointer;
              background-color: #f0f6ff;
            }

            div {
              line-height: 66px;

              img {
                margin-right: 20px;
                width: 28px;
                height: 28px;
                border-radius: 3px;
              }

              a {
                text-decoration: none;
                font-size: 15px;
                color: #131b26;

                &:hover {
                  color: #3A8BFF;
                }
              }
            }
          }
        }
      }
    }
  }

  .uploader {
    width: 880px;
    /*padding: 15px;*/
    /*margin: 20px auto 0;*/
    font-size: 14px;
    /*box-shadow: 0 0 10px rgba(0, 0, 0, .4);*/

    .uploader-btn {
      margin-right: 4px;
      color: #fff;
      padding: 6px 16px;
    }

    .upfile {
      border: 1px solid #409eff;
      background: #409eff;
    }

    .updir {
      border: 1px solid #67c23a;
      background: #67c23a;
    }

    .uploader-list {
      max-height: 440px;
      overflow: auto;
      overflow-x: hidden;
      overflow-y: auto;

      height: 356px;

      /deep/ .iconfont {
        font-size: 18px;
        color: #409eff;
      }
    }

  }

  //手机等小屏幕手持设备。当设备宽度  在  320px和768px之间时,执行当前的css
  @media only screen and (min-width: 320px) and (max-width: 768px) {
    .uploader {
      width: 98%;
      padding: 0;
      box-shadow: none;
    }
  }

  .contextmenu {
    margin: 0;
    background: #fff;
    z-index: 3000;
    position: fixed;
    list-style-type: none;
    padding: 5px 0;
    border-radius: 4px;
    font-size: 12px;
    font-weight: 400;
    color: #333;
    box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);
  }

  .contextmenu li {
    margin: 0;
    padding: 7px 16px;
    cursor: pointer;
  }

  .contextmenu li:hover {
    background-color: rgb(3, 125, 243);;
    color: white;
  }
</style>
